//
// Created by HP on 2022/3/9.
//

// std
#include <math.h>

#include "renderMath.h"

double bezier_quadratic_dev(BezierQuadratic *curve, double t) {
    double p1_2x = 2 * curve->p1.x;
    double p1_2y = 2 * curve->p1.y;
    double x = 2 * t * (curve->p0.x - p1_2x + curve->p2.x) +  p1_2x - curve->p0.x + curve->p0.x;
    double y = 2 * t * (curve->p0.y - p1_2y + curve->p2.y) +  p1_2y - curve->p0.y + curve->p0.y;

    return sqrt(x*x + y*y);
}

double simpson(BezierQuadratic *curve, double l, double r) {
    double mid_l = (2.0 * l + r) / 3.0;
    double mid_r = (l + 2.0 * r) / 3.0;
    double l_value = bezier_quadratic_dev(curve, l);
    double ml_value = bezier_quadratic_dev(curve, mid_l);
    double mr_value = bezier_quadratic_dev(curve, mid_r);
    double r_value = bezier_quadratic_dev(curve, r);

    double result = (l_value + 3.0 * (ml_value + mr_value) + r_value) * (r - l) / 8.0;
    return result;
}

double bezier_len(BezierQuadratic *curve, double l, double r, double eps) {
    double mid = (l + r) / 2.0;
    double ST = simpson(curve, l, r);
    double SL = simpson(curve, l, mid);
    double SR = simpson(curve, mid, r);
    double ans = SL + SR - ST;
    if(fabs(ans) <= 15.0 * eps)  {
        return SL + SR + ans / 15.0;
    }
    return bezier_len(curve, l, mid, eps / 2.0) + bezier_len(curve, mid, r, eps / 2.0);
}

// Px(t) = t^2 * (P0.x - 2P1.x + P2.x) + t * (2P1.x - P0.x) + P0.x --- 3
// Py(t) = t^2 * (P0.y - 2P1.y + P2.y) + t * (2P1.y - P0.y) + P0.y --- 4
//               |-------- a --------|       |----- b ----|
// Px'(t) = 2t * a.x + b.x  --- 5
// Py'(t) = 2t * a.y + b.y  --- 6
// V(t) = sqrt( Px'(t)^2 + Py'(t)^2 )
void generate(BezierQuadratic *curve, Vertex *vertices, int cnt) {
    // 生成起点和终点
    vertices[0] = curve->p0;
    vertices[cnt - 1] = curve->p2;
    // 获取长度
    double len = bezier_len(curve, 0, 1, 0.1);
    // 计算每一次运动的长度
    double dl = len / (cnt - 1);
    // 循环中的常量
    double p1_2x = 2 * curve->p1.x;
    double p1_2y = 2 * curve->p1.y;
    double ax = curve->p0.x - p1_2x + curve->p2.x;
    double bx = p1_2x - curve->p0.x;
    double ay = curve->p0.y - p1_2y + curve->p2.y;
    double by = p1_2y - curve->p0.y;
    // 初始 t
    double t = 0.0;
    for (int i = 1; i < cnt - 1; i++) {
        // 计算当前的瞬时速度
        double vx = 2.0 * t * ax + bx;
        double vy = 2.0 * t * ay + by;
        double v = sqrt(vx*vx + vy*vy);
        // 计算移动的时间
        double dt = dl / v;
        double t1 = t + dt;
        vx = 2.0 * t1 * ax + bx;
        vy = 2.0 * t1 * ay + by;
        double v1 = sqrt(vx*vx + vy*vy);
        double avg_v = (v + v1) / 2.0;
        dt = dl / avg_v;
        // 计算当前 t
        t += dt;
        // 计算当前坐标
        double t2 = t * t;
        double x = t2 * ax + t * bx + curve->p0.x;
        double y = t2 * ay + t * by + curve->p0.y;
        vertices[i].x = x;
        vertices[i].y = y;
    }
}
